
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>

#include <common/alloc.h>

static const char * all_countries = "/data/tmp/conc/geoname/extract/allCountries.txt";
//static const char * all_countries = "D:/tmp/vkon-conc/geoname/allCountries/allCountries.txt";

#define MAX_FILE_BUF_LEN (65536)

// print word-by-word
static void print_word_by_word(char * cur)
{
    char * begin = cur;

    while (*cur != 0)
    {
        if (*cur == '\t')
        {
            *cur++ = 0;
            fprintf(stdout, "%s|", begin);
            begin = cur;
        }
        else
        {
            ++cur;
        }
    }

    fprintf(stdout, "%s\n", begin);
}

static void print_records(bool word_by_word, int max_recs)
{
    FILE * f = fopen(all_countries, "rb");
    char * buf = NULL;

    buf = xmalloc(MAX_FILE_BUF_LEN);

    if (f != NULL)
    {
        int bytes_read = fread(buf, 1, MAX_FILE_BUF_LEN, f);

        if (bytes_read > 0)
        {
            char * begin = buf;
            const char * end = begin + bytes_read;
            int rec;

            for (rec = 0; begin != end && rec < max_recs; ++rec)
            {
                char * cur = begin;
                while (*begin != '\n')
                {
                    ++begin;
                    if (begin != end)
                    {
                        continue;
                    }

                    // buffer is too small?
                    if (cur == buf)
                    {
                        fprintf(stderr, "error: source buffer is too small\n");
                        abort();
                    }

                    // can read more?
                    if (bytes_read == MAX_FILE_BUF_LEN)
                    {
                        char * new_buf = xmalloc(MAX_FILE_BUF_LEN);
                        size_t copied = begin - cur;

                        // copy current contents to this buffer
                        memcpy(new_buf, cur, copied);
                        xfree(buf);
                        buf = new_buf;

                        // fix new values to make them point to the new locations
                        cur = buf;
                        begin = buf + copied;

                        bytes_read = fread(begin, 1, MAX_FILE_BUF_LEN - copied, f);
                        end = begin + bytes_read;

                        bytes_read += copied;
                        continue;
                    }

                    // go back to the previous position to put
                    // trailing zero at the end of the buffer then,
                    // expecting whitespace at the end of file
                    --begin;

                    break;
                }

                // put 0 at this string and advance to the next character
                *begin++ = 0;

                if (!word_by_word)
                {
                    fprintf(stdout, "%s\n", cur);
                }
                else
                {
                    print_word_by_word(cur);
                }
            }
        }
    }
    else
    {
        fprintf(stderr, "error: can't open %s\n", all_countries);
    }


    // free resources
    if (f != NULL)
    {
        fclose(f);
        f = NULL;
    }

    xfree(buf);
}

void test_unihash();
void test_tree1();
void test_tree2();
void test_import1();
void test_import2();

int main(int argc, char ** argv)
{
    if (argc == 0 && argv != NULL)
    {
        test_unihash();
        print_word_by_word(NULL);
        print_records(false, 1024);
        test_tree1();
    }
    else
    {
        test_import2();
        //test_import1();
        //print_records(false, 1024);
        //test_unihash();
        //test_tree2();
    }

    return 0;
}
